#ifndef _SD_CARD_H_
#define _SD_CARD_H_

#include "types.h"

#define MMC0_BASE		0x01C40000
#define MMC1_BASE		0x01E1B000

//#warning: Check default MMC base
#define DEFAULT_MMC		MMC0_BASE

#define MMC_CTL			*((volatile uint32_t *)DEFAULT_MMC)
#define MMC_CLK			*((volatile uint32_t *)(DEFAULT_MMC + 0x04))
#define MMC_ST0			*((volatile uint32_t *)(DEFAULT_MMC + 0x08))
#define MMC_ST1			*((volatile uint32_t *)(DEFAULT_MMC + 0x0C))
#define MMC_IM			*((volatile uint32_t *)(DEFAULT_MMC + 0x10))
#define MMC_CTOR		*((volatile uint32_t *)(DEFAULT_MMC + 0x14))
#define MMC_CTOD		*((volatile uint32_t *)(DEFAULT_MMC + 0x18))
#define MMC_BLEN		*((volatile uint32_t *)(DEFAULT_MMC + 0x1C))
#define MMC_NBLK		*((volatile uint32_t *)(DEFAULT_MMC + 0x20))
#define MMC_NBLC		*((volatile uint32_t *)(DEFAULT_MMC + 0x24))
#define MMC_DDR			*((volatile uint32_t *)(DEFAULT_MMC + 0x28))
#define MMC_DXR			*((volatile uint32_t *)(DEFAULT_MMC + 0x2C))
#define MMC_CMD			*((volatile uint32_t *)(DEFAULT_MMC + 0x30))
#define MMC_ARGHL		*((volatile uint32_t *)(DEFAULT_MMC + 0x34))
#define MMC_RSP01		*((volatile uint32_t *)(DEFAULT_MMC + 0x38))
#define MMC_RSP23		*((volatile uint32_t *)(DEFAULT_MMC + 0x3C))
#define MMC_RSP45		*((volatile uint32_t *)(DEFAULT_MMC + 0x40))
#define MMC_RSP67		*((volatile uint32_t *)(DEFAULT_MMC + 0x44))
#define MMC_DRSP		*((volatile uint32_t *)(DEFAULT_MMC + 0x48))
#define MMC_CIDX		*((volatile uint32_t *)(DEFAULT_MMC + 0x50))
#define SDIO_CTL		*((volatile uint32_t *)(DEFAULT_MMC + 0x64))
#define SDIO_ST0		*((volatile uint32_t *)(DEFAULT_MMC + 0x68))
#define SDIO_IEN		*((volatile uint32_t *)(DEFAULT_MMC + 0x6C))
#define SDIO_IST		*((volatile uint32_t *)(DEFAULT_MMC + 0x70))
#define MMC_FIFOCTL		*((volatile uint32_t *)(DEFAULT_MMC + 0x74))


typedef enum
{
	NO_RESPONSE,
	R1,
	R2,
	R3,
	R4,
	R5,
	R6
}sd_expected_response_t;

typedef struct
{	
	union
	{
		uint32_t value;		// r1:card_status, r3:ocr, r6:RCA_cardStatus
		uint8_t command_index;
		uint8_t crc7;
	}r1_r3_r6;

	union
	{
		uint32_t cid_csr3;
		uint32_t cid_csr2;
		uint32_t cid_csr1;
		uint32_t cid_csr0;
	}r2;

	union
	{
		uint16_t new_rca;
		uint16_t card_status;
		uint8_t command_index;
		uint8_t crc7;
	}r6;

	uint8_t start_bit:1;
	uint8_t transmission_bit:1;
	uint8_t end_bit:1;

	uint8_t timedout:1;
	uint8_t busy:1;

	uint8_t unused:3;

}sd_command_response_t;

		
		

typedef struct
{
	bool transfer_triggered;
	bool trx_clear;
	bool init_clock;
	bool data_transfer;
	bool stream_enable;
	bool read_write;	// 0:read, 1:write
	bool busy_expected;
	bool push_pull;
	uint8_t command;
	uint32_t arg;		// command argument
	sd_expected_response_t expected_rsp;
	
}sd_command_t;

static sd_command_t null_sd_command = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

#define RESET_COMMAND(cmd)	(cmd) = null_sd_command

//#warning: MMC_CIDX not cleared while sending a command

#endif
